// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using Microsoft.WindowsAPICodePack.DirectX.Direct2D1;
using Microsoft.WindowsAPICodePack.DirectX.DirectWrite;

namespace D2DPaint
{
    abstract class DrawingShape
    {
        protected Pain2DForm _parent;
        protected bool _fill;

        protected internal abstract void Draw(RenderTarget renderTarget);

        protected internal abstract Point2F EndPoint
        {
            set;
        }

        protected DrawingShape(Pain2DForm parent)
        {
            this._parent = parent;
        }

        protected DrawingShape(Pain2DForm parent, bool fill) : this(parent)
        {
            this._fill = fill;
        }
    }

    internal class Line : DrawingShape
    {        
        internal Point2F _point0, _point1;
        internal float _strokeWidth;
        internal int _selectedBrushIndex;

        internal Line(Pain2DForm parent, Point2F point0, Point2F point1, float strokeWidth, int selectedBrush) : base(parent)
        {
            _point0 = point0;
            _point1 = point1;
            _strokeWidth = strokeWidth;
            _selectedBrushIndex = selectedBrush;

        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            renderTarget.DrawLine(_point0, _point1, _parent.brushes[_selectedBrushIndex], _strokeWidth);
        }

        protected internal override Point2F EndPoint
        {
            set
            {
                _point1 = value;
            }
        }
    }

    internal class DrawingBitmap : DrawingShape
    {
        internal RectF _rect;
        internal D2DBitmap _bitmap;
        internal float _transparency;

        internal DrawingBitmap(Pain2DForm parent, RectF rect, D2DBitmap bitmap, float transparency)
            : base(parent)
        {
            _rect = rect;
            _bitmap = bitmap;
            _transparency = transparency;
        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            renderTarget.DrawBitmap(_bitmap, _transparency, BitmapInterpolationMode.Linear, _rect);
        }

        protected internal override Point2F EndPoint
        {
            set
            {
                _rect.right = value.X;
                _rect.bottom = value.Y;
            }
        }
    }

    internal class RoundRectangle : DrawingShape
    {
        internal RoundedRect _rect;
        internal float _strokeWidth;
        internal int _selectedBrushIndex;


        internal RoundRectangle(Pain2DForm parent, RoundedRect rect, float strokeWidth, int selectedBrush, bool fill)
            : base(parent, fill)
        {
            _rect = rect;
            _strokeWidth = strokeWidth;
            _selectedBrushIndex = selectedBrush;
        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            if (_fill)
            {
                renderTarget.FillRoundedRectangle(_rect, _parent.brushes[_selectedBrushIndex]);
            }
            else
            {
                renderTarget.DrawRoundedRectangle(_rect, _parent.brushes[_selectedBrushIndex], _strokeWidth);
            }
        }

        protected internal override Point2F EndPoint
        {
            set
            {
                _rect.Rect.right = value.X;
                _rect.Rect.bottom = value.Y;
            }
        }
    }

    internal class RectangleShape : DrawingShape
    {
        internal RectF _rect;
        internal float _strokeWidth;
        internal int _selectedBrushIndex;


        internal RectangleShape(Pain2DForm parent, RectF rect, float strokeWidth, int selectedBrush, bool fill)
            : base(parent, fill)
        {
            _rect = rect;
            _strokeWidth = strokeWidth;
            _selectedBrushIndex = selectedBrush;
        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            if (_fill)
            {
                renderTarget.FillRectangle(_rect, _parent.brushes[_selectedBrushIndex]);
            }
            else
            {
                renderTarget.DrawRectangle(_rect, _parent.brushes[_selectedBrushIndex], _strokeWidth);
            }
        }
        protected internal override Point2F EndPoint
        {
            set
            {
                _rect.right = value.X;
                _rect.bottom = value.Y;
            }
        }
    }

    internal class TextShape : DrawingShape
    {
        internal float _maxX;
        internal float _maxY;
        internal Point2F _point0;
        internal TextLayout _textLayout;
        internal int _selectedBrushIndex;

        internal TextShape(Pain2DForm parent, TextLayout textLayout, Point2F startPoint, float maxX, float maxY, int selectedBrush)
            : base(parent)
        {
            _maxX = maxX;
            _maxY = maxY;
            _textLayout = textLayout;
            _selectedBrushIndex = selectedBrush;
            _point0 = startPoint;
        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            renderTarget.DrawTextLayout(
                _point0, _textLayout, _parent.brushes[_selectedBrushIndex]);
        }

        protected internal override Point2F EndPoint
        {
            set
            {
                _textLayout.MaxWidth = Math.Abs(_point0.X - value.X);
                _textLayout.MaxHeight = Math.Abs(_point0.Y - value.Y);
            }
        }
    }

    internal class EllipseShape : DrawingShape
    {
        internal Ellipse _ellipse;
        internal float _strokeWidth;
        internal int _selectedBrushIndex;


        internal EllipseShape(Pain2DForm parent, Ellipse ellipse, float strokeWidth, int selectedBrush, bool fill)
            : base(parent, fill)
        {
            _ellipse = ellipse;
            _strokeWidth = strokeWidth;
            _selectedBrushIndex = selectedBrush;
        }

        protected internal override void Draw(RenderTarget renderTarget)
        {
            if (_fill)
            {
                renderTarget.FillEllipse(_ellipse, _parent.brushes[_selectedBrushIndex]);
            }
            else
            {
                renderTarget.DrawEllipse(_ellipse, _parent.brushes[_selectedBrushIndex], _strokeWidth);
            }
        }
        protected internal override Point2F EndPoint
        {
            set
            {
                _ellipse.RadiusX = value.X - _ellipse.Point.X;
                _ellipse.RadiusY = value.Y - _ellipse.Point.Y;
            }
        }
    }
}
